export let JSWebrtc = {
	Player: null,
	VideoElement: null,
	CreateVideoElements: function () {
		let elements = document.querySelectorAll('.jswebrtc');
		for (let i = 0; i < elements.length; i++) {
			new JSWebrtc.VideoElement(elements[i]);
		}
	},
	FillQuery: function (query_string, obj) {
		obj.user_query = {};
		if (query_string.length == 0) {
			return;
		}
		if (query_string.indexOf('?') >= 0) {
			query_string = query_string.split('?')[1];
		}
		let queries = query_string.split('&');
		for (let i = 0; i < queries.length; i++) {
			let query = queries[i].split('=');
			obj[query[0]] = query[1];
			obj.user_query[query[0]] = query[1];
		}
		if (obj.domain) {
			obj.vhost = obj.domain;
		}
	},
	ParseUrl: function (rtmp_url) {
		let a = document.createElement('a');
		a.href = rtmp_url.replace('rtmp://', 'http://').replace('webrtc://', 'http://').replace('rtc://', 'http://');
		let vhost = a.hostname;
		let app = a.pathname.substr(1, a.pathname.lastIndexOf('/') - 1);
		let stream = a.pathname.substr(a.pathname.lastIndexOf('/') + 1);
		app = app.replace('...vhost...', '?vhost=');
		if (app.indexOf('?') >= 0) {
			let params = app.substr(app.indexOf('?'));
			app = app.substr(0, app.indexOf('?'));
			if (params.indexOf('vhost=') > 0) {
				vhost = params.substr(params.indexOf('vhost=') + 'vhost='.length);
				if (vhost.indexOf('&') > 0) {
					vhost = vhost.substr(0, vhost.indexOf('&'));
				}
			}
		}
		if (a.hostname == vhost) {
			let re = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
			if (re.test(a.hostname)) {
				vhost = '__defaultVhost__';
			}
		}
		let schema = 'rtmp';
		if (rtmp_url.indexOf('://') > 0) {
			schema = rtmp_url.substr(0, rtmp_url.indexOf('://'));
		}
		let port = a.port;
		if (!port) {
			if (schema === 'http') {
				port = 80;
			} else if (schema === 'https') {
				port = 443;
			} else if (schema === 'rtmp') {
				port = 1935;
			} else if (schema === 'webrtc' || schema === 'rtc') {
				port = 1985;
			}
		}
		let ret = {
			url: rtmp_url,
			schema: schema,
			server: a.hostname,
			port: port,
			vhost: vhost,
			app: app,
			stream: stream
		};
		JSWebrtc.FillQuery(a.search, ret);
		return ret;
	},
	HttpPost: function (url, data) {
		return new Promise(function (resolve, reject) {
			let xhr = new XMLHttpRequest();
			xhr.onreadystatechange = function () {
				if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status < 300) {
					let respone = JSON.parse(xhr.responseText);
					xhr.onreadystatechange = new Function();
					xhr = null;
					resolve(respone);
				}
			};
			xhr.open('POST', url, true);
			xhr.timeout = 5e3;
			xhr.responseType = 'text';
			xhr.setRequestHeader('Content-Type', 'application/json');
			xhr.send(data);
		});
	}
};
if (document.readyState === 'complete') {
	JSWebrtc.CreateVideoElements();
} else {
	document.addEventListener('DOMContentLoaded', JSWebrtc.CreateVideoElements);
}
JSWebrtc.VideoElement = (function () {
	'use strict';
	let VideoElement = function (element) {
		let url = element.dataset.url;
		if (!url) {
			throw 'VideoElement has no `data-url` attribute';
		}
		let addStyles = function (element, styles) {
			for (let name in styles) {
				element.style[name] = styles[name];
			}
		};
		this.container = element;
		addStyles(this.container, {
			display: 'inline-block',
			position: 'relative',
			minWidth: '80px',
			minHeight: '80px'
		});
		this.video = document.createElement('video');
		this.video.width = 960;
		this.video.height = 540;
		addStyles(this.video, { display: 'block', width: '100%' });
		this.container.appendChild(this.video);
		this.playButton = document.createElement('div');
		this.playButton.innerHTML = VideoElement.PLAY_BUTTON;
		addStyles(this.playButton, {
			zIndex: 2,
			position: 'absolute',
			top: '0',
			bottom: '0',
			left: '0',
			right: '0',
			maxWidth: '75px',
			maxHeight: '75px',
			margin: 'auto',
			opacity: '0.7',
			cursor: 'pointer'
		});
		this.container.appendChild(this.playButton);
		let options = { video: this.video };
		for (let option in element.dataset) {
			try {
				options[option] = JSON.parse(element.dataset[option]);
			} catch (err) {
				options[option] = element.dataset[option];
			}
		}
		this.player = new JSWebrtc.Player(url, options);
		element.playerInstance = this.player;
		if (options.poster && !options.autoplay) {
			options.decodeFirstFrame = false;
			this.poster = new Image();
			this.poster.src = options.poster;
			this.poster.addEventListener('load', this.posterLoaded);
			addStyles(this.poster, {
				display: 'block',
				zIndex: 1,
				position: 'absolute',
				top: 0,
				left: 0,
				bottom: 0,
				right: 0
			});
			this.container.appendChild(this.poster);
		}
		if (!this.player.options.streaming) {
			this.container.addEventListener('click', this.onClick.bind(this));
		}
		if (options.autoplay) {
			this.playButton.style.display = 'none';
		}
		if (this.player.audioOut && !this.player.audioOut.unlocked) {
			let unlockAudioElement = this.container;
			if (options.autoplay) {
				this.unmuteButton = document.createElement('div');
				this.unmuteButton.innerHTML = VideoElement.UNMUTE_BUTTON;
				addStyles(this.unmuteButton, {
					zIndex: 2,
					position: 'absolute',
					bottom: '10px',
					right: '20px',
					width: '75px',
					height: '75px',
					margin: 'auto',
					opacity: '0.7',
					cursor: 'pointer'
				});
				this.container.appendChild(this.unmuteButton);
				unlockAudioElement = this.unmuteButton;
			}
			this.unlockAudioBound = this.onUnlockAudio.bind(this, unlockAudioElement);
			unlockAudioElement.addEventListener('touchstart', this.unlockAudioBound, false);
			unlockAudioElement.addEventListener('click', this.unlockAudioBound, true);
		}
	};

	VideoElement.prototype.onUnlockAudio = function (element, ev) {
		if (this.unmuteButton) {
			ev.preventDefault();
			ev.stopPropagation();
		}
		this.player.audioOut.unlock(
			function () {
				if (this.unmuteButton) {
					this.unmuteButton.style.display = 'none';
				}
				element.removeEventListener('touchstart', this.unlockAudioBound);
				element.removeEventListener('click', this.unlockAudioBound);
			}.bind(this)
		);
	};
	VideoElement.prototype.onClick = function (ev) {
		if (this.player.isPlaying) {
			this.player.pause();
			this.playButton.style.display = 'block';
		} else {
			this.player.play();
			this.playButton.style.display = 'none';
			if (this.poster) {
				this.poster.style.display = 'none';
			}
		}
	};
	VideoElement.PLAY_BUTTON =
		'<svg style="max-width: 75px; max-height: 75px;" ' +
		'viewBox="0 0 200 200" alt="Play video">' +
		'<circle cx="100" cy="100" r="90" fill="none" ' +
		'stroke-width="15" stroke="#fff"/>' +
		'<polygon points="70, 55 70, 145 145, 100" fill="#fff"/>' +
		'</svg>';
	VideoElement.UNMUTE_BUTTON =
		'<svg style="max-width: 75px; max-height: 75px;" viewBox="0 0 75 75">' +
		'<polygon class="audio-speaker" stroke="none" fill="#fff" ' +
		'points="39,13 22,28 6,28 6,47 21,47 39,62 39,13"/>' +
		'<g stroke="#fff" stroke-width="5">' +
		'<path d="M 49,50 69,26"/>' +
		'<path d="M 69,50 49,26"/>' +
		'</g>' +
		'</svg>';
	return VideoElement;
})();
JSWebrtc.Player = (function () {
	'use strict';
	let Player = function (url, options) {
		this.options = options || {};
		if (!url.match(/^webrtc?:\/\//)) {
			throw 'JSWebrtc just work with webrtc';
		}
		if (!this.options.video) {
			throw 'VideoElement is null';
		}
		this.urlParams = JSWebrtc.ParseUrl(url);
		this.pc = null;
		this.autoplay = !!options.autoplay || false;
		this.paused = true;
		if (this.autoplay) {
			this.options.video.muted = true;
		}
		this.startLoading();
	};
	Player.prototype.startLoading = function () {
		let _self = this;
		if (_self.pc) {
			_self.pc.close();
		}
		_self.pc = new RTCPeerConnection(null);
		_self.pc.ontrack = function (event) {
			_self.options.video['srcObject'] = event.streams[0];
		};
		_self.pc.addTransceiver('audio', { direction: 'recvonly' });
		_self.pc.addTransceiver('video', { direction: 'recvonly' });
		_self.pc
			.createOffer()
			.then(function (offer) {
				return _self.pc.setLocalDescription(offer).then(function () {
					return offer;
				});
			})
			.then(function (offer) {
				return new Promise(function (resolve, reject) {
					let port = _self.urlParams.port || 1985;
					let api = _self.urlParams.user_query.play || '/rtc/v1/play/';
					if (api.lastIndexOf('/') != api.length - 1) {
						api += '/';
					}
					let url = 'http://' + _self.urlParams.server + ':' + port + api;
					for (let key in _self.urlParams.user_query) {
						if (key != 'api' && key != 'play') {
							url += '&' + key + '=' + _self.urlParams.user_query[key];
						}
					}
					let data = {
						api: url,
						streamurl: _self.urlParams.url,
						clientip: null,
						sdp: offer.sdp,
						tid: Number(parseInt(new Date().getTime() * Math.random() * 100))
							.toString(16)
							.slice(0, 7)
					};
					JSWebrtc.HttpPost(url, JSON.stringify(data)).then(
						function (res) {
							resolve(res.sdp);
						},
						function (rej) {
							reject(rej);
						}
					);
				});
			})
			.then(function (answer) {
				return _self.pc.setRemoteDescription(new RTCSessionDescription({ type: 'answer', sdp: answer }));
			})
			.catch(function (reason) {
				throw reason;
			});
		if (this.autoplay) {
			this.play();
		}
	};
	Player.prototype.play = function (ev) {
		if (this.animationId) {
			return;
		}
		this.animationId = requestAnimationFrame(this.update.bind(this));
		this.paused = false;
	};
	Player.prototype.pause = function (ev) {
		if (this.paused) {
			return;
		}
		cancelAnimationFrame(this.animationId);
		this.animationId = null;
		this.isPlaying = false;
		this.paused = true;
		this.options.video.pause();
		this.options.video.removeAttribute('src');
		this.options.video.load();
		this.options.video = null;
		if (this.options.onPause) {
			this.options.onPause(this);
		}
	};
	Player.prototype.stop = function (ev) {
		this.pause();
	};
	Player.prototype.close = function () {
		this.pause();
		this.pc && this.pc.close() && this.pc.destroy();
		this.pc = null;
		this.audioOut && this.audioOut.destroy();
		this.audioOut = null;
		this.options = null;
		this.player = null;
		// console.log('srs关掉视频');
	};
	Player.prototype.update = function () {
		this.animationId = requestAnimationFrame(this.update.bind(this));
		if (this.options.video.readyState < 4) {
			return;
		}
		if (!this.isPlaying) {
			this.isPlaying = true;
			this.options.video.play();
			if (this.options.onPlay) {
				this.options.onPlay(this);
			}
		}
	};
	return Player;
})();
